package net.media.datafw.transport.transporters;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import net.media.datafw.transport.TransportException;
import net.media.datafw.transport.Transporter;
import net.media.datafw.transport.model.TransportField;
import net.media.datafw.transport.model.Transportable;
import net.media.datafw.transport.utils.TransporterUtil;

public class ByteCodeTransporter extends Transporter {
	public static final boolean BYTECODE_ISARRAY_TRUE = true;
	public static final boolean BYTECODE_ISARRAY_FALSE = false;

	public static final boolean BYTECODE_HAS_MORE_FIELDS_TRUE = true;
	public static final boolean BYTECODE_HAS_MORE_FIELDS_FALSE = false;

	ByteArrayOutputStream baos = null;

	@Override
	protected void writeTransportable(Transportable data, Object serilizedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serilizedData;
			dos.writeUTF(readClassName(data.getClass()));
			serializeTransportable(data, dos);
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void writeTransportableArray(Transportable[] data, Object serilizedData) throws TransportException {
		try {
			if (data != null) {
				DataOutputStream dos = (DataOutputStream) serilizedData;
				dos.writeInt(data.length);
				for (int i = 0; i < data.length; i++) {
					writeTransportable(data[i], dos);
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeTransportable(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				Transportable[] transportableArray = (Transportable[]) objectData;
				dos.writeInt(transportableArray.length);
				for (int i = 0; i < transportableArray.length; i++) {
					dos.writeUTF(readClassName(transportableArray[i].getClass()));
					serializeTransportable((Transportable) transportableArray[i], dos);
				}
			} else {
				dos.writeUTF(readClassName(objectData.getClass()));
				serializeTransportable((Transportable) objectData, dos);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected Object initialiseTrasportableArray() throws TransportException {
		DataOutputStream dos = null;
		try {
			baos = new ByteArrayOutputStream();
			dos = new DataOutputStream(baos);
			dos.writeBoolean(BYTECODE_ISARRAY_TRUE);
		} catch (Exception e) {
			throw new TransportException(e);
		}
		return dos;
	}

	@Override
	protected Object initialiseTrasportable() throws TransportException {
		DataOutputStream dos = null;
		try {
			baos = new ByteArrayOutputStream();
			dos = new DataOutputStream(baos);
			dos.writeBoolean(BYTECODE_ISARRAY_FALSE);
		} catch (Exception e) {
			throw new TransportException(e);
		}
		return dos;
	}

	@Override
	protected void serializeBoolean(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				boolean[] data;
				if (field.isPrimitive()) {
					data = (boolean[]) objectData;
				} else {
					Boolean[] dataArr = (Boolean[]) objectData;
					data = TransporterUtil.converBooleanArray(dataArr);
				}

				dos.writeInt(data.length);
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					dos.writeBoolean(data[dataIdx]);
				}
			} else {
				dos.writeBoolean(((Boolean) objectData).booleanValue());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeByte(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				byte[] data;
				if (field.isPrimitive()) {
					data = (byte[]) objectData;
				} else {
					Byte[] dataArr = (Byte[]) objectData;
					data = TransporterUtil.converByteArray(dataArr);
				}

				dos.writeInt(data.length);
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					dos.writeByte(data[dataIdx]);
				}
			} else {
				dos.writeByte(((Byte) objectData).byteValue());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeCharacter(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				char[] data;
				if (field.isPrimitive()) {
					data = (char[]) objectData;
				} else {
					Character[] dataArr = (Character[]) objectData;
					data = TransporterUtil.converCharacterArray(dataArr);
				}

				dos.writeInt(data.length);
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					dos.writeChar(data[dataIdx]);
				}
			} else {
				dos.writeChar(((Character) objectData).charValue());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeShort(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				short[] data;
				if (field.isPrimitive()) {
					data = (short[]) objectData;
				} else {
					Short[] dataArr = (Short[]) objectData;
					data = TransporterUtil.converShortArray(dataArr);
				}

				dos.writeInt(data.length);
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					dos.writeShort(data[dataIdx]);
				}
			} else {
				dos.writeShort(((Short) objectData).shortValue());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeInteger(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				int[] data;
				if (field.isPrimitive()) {
					data = (int[]) objectData;
				} else {
					Integer[] dataArr = (Integer[]) objectData;
					data = TransporterUtil.converIntegerArray(dataArr);
				}

				dos.writeInt(data.length);
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					dos.writeInt(data[dataIdx]);
				}
			} else {
				dos.writeInt(((Integer) objectData).intValue());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeLong(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				long[] data;
				if (field.isPrimitive()) {
					data = (long[]) objectData;
				} else {
					Long[] dataArr = (Long[]) objectData;
					data = TransporterUtil.converLongArray(dataArr);
				}

				dos.writeInt(data.length);
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					dos.writeLong(data[dataIdx]);
				}
			} else {
				dos.writeLong(((Long) objectData).longValue());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeFloat(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				float[] data;
				if (field.isPrimitive()) {
					data = (float[]) objectData;
				} else {
					Float[] dataArr = (Float[]) objectData;
					data = TransporterUtil.converFloatArray(dataArr);
				}

				dos.writeInt(data.length);
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					dos.writeFloat(data[dataIdx]);
				}
			} else {
				dos.writeFloat(((Float) objectData).floatValue());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeDouble(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				double[] data;
				if (field.isPrimitive()) {
					data = (double[]) objectData;
				} else {
					Double[] dataArr = (Double[]) objectData;
					data = TransporterUtil.converDoubleArray(dataArr);
				}

				dos.writeInt(data.length);
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					dos.writeDouble(data[dataIdx]);
				}
			} else {
				dos.writeDouble(((Double) objectData).doubleValue());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeString(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				String[] data = (String[]) objectData;
				dos.writeInt(data.length);
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					dos.writeUTF(data[dataIdx]);
				}
			} else {
				dos.writeUTF((String) objectData);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void serializeDate(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				Date[] data = (Date[]) objectData;
				dos.writeInt(data.length);
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					dos.writeUTF(data[dataIdx].toString());
				}
			} else {
				dos.writeUTF(objectData.toString());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void serializeArrayList(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				ArrayList<Object>[] data = (ArrayList<Object>[]) objectData;
				dos.writeInt(data.length);
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					processArrayList(field, data[dataIdx], field.getComponentValueType(), dos);
				}
			} else {
				ArrayList<Object> data = (ArrayList<Object>) objectData;
				processArrayList(field, data, field.getComponentValueType(), dos);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void processArrayList(TransportField field, ArrayList<Object> data, Type genericValueClass, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			dos.writeInt(data.size());
			if ((Boolean.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					dos.writeBoolean(((Boolean) data.get(arrarIdx)).booleanValue());
				}
			} else if ((Byte.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					dos.writeByte(((Byte) data.get(arrarIdx)).byteValue());
				}
			} else if ((Character.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					dos.writeChar(((Character) data.get(arrarIdx)).charValue());
				}
			} else if ((Short.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					dos.writeShort(((Short) data.get(arrarIdx)).shortValue());
				}
			} else if ((Integer.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					dos.writeInt(((Integer) data.get(arrarIdx)).intValue());
				}
			} else if ((Long.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					dos.writeLong(((Long) data.get(arrarIdx)).longValue());
				}
			} else if ((Float.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					dos.writeFloat(((Float) data.get(arrarIdx)).floatValue());
				}
			} else if ((Double.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					dos.writeDouble(((Double) data.get(arrarIdx)).doubleValue());
				}
			} else if ((String.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					dos.writeUTF((String) data.get(arrarIdx));
				}
			} else if (isTransportable(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < data.size(); arrarIdx++) {
					writeTransportable((Transportable) data.get(arrarIdx), dos);
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void serializeHashMap(TransportField field, Object objectData, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			if (field.isArray()) {
				HashMap<Object, Object>[] data = (HashMap<Object, Object>[]) objectData;
				dos.writeInt(data.length);
				for (int dataIdx = 0; dataIdx < data.length; dataIdx++) {
					processHashMap(field, data[dataIdx], field.getComponentValueType(), dos);
				}
			} else {
				HashMap<Object, Object> data = (HashMap<Object, Object>) objectData;
				processHashMap(field, data, field.getComponentValueType(), dos);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void processHashMap(TransportField field, HashMap<Object, Object> data, Type genericValueClass, Object serializedData) throws TransportException {

		try {
			Set<Object> keys = data.keySet();

			DataOutputStream dos = (DataOutputStream) serializedData;
			dos.writeInt(keys.size());

			Iterator<?> keyIterator = keys.iterator();
			if ((Boolean.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					dos.writeUTF(key);
					dos.writeBoolean(((Boolean) data.get(key)).booleanValue());
				}
			} else if ((Byte.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					dos.writeUTF(key);
					dos.writeByte(((Byte) data.get(key)).byteValue());
				}
			} else if ((Character.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					dos.writeUTF(key);
					dos.writeChar(((Character) data.get(key)).charValue());
				}
			} else if ((Short.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					dos.writeUTF(key);
					dos.writeShort(((Short) data.get(key)).shortValue());
				}
			} else if ((Integer.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					dos.writeUTF(key);
					dos.writeInt(((Integer) data.get(key)).intValue());
				}
			} else if ((Long.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					dos.writeUTF(key);
					dos.writeLong(((Long) data.get(key)).longValue());
				}
			} else if ((Float.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					dos.writeUTF(key);
					dos.writeFloat(((Float) data.get(key)).floatValue());
				}
			} else if ((Double.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					dos.writeUTF(key);
					dos.writeDouble(((Double) data.get(key)).doubleValue());
				}
			} else if ((String.class).equals(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					dos.writeUTF(key);
					dos.writeUTF((String) data.get(key));
				}
			} else if (isTransportable(genericValueClass)) {
				while (keyIterator.hasNext()) {
					String key = (String) keyIterator.next();
					dos.writeUTF(key);
					writeTransportable((Transportable) data.get(key), dos);
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void onSerializeField(TransportField field, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			dos.writeBoolean(BYTECODE_HAS_MORE_FIELDS_TRUE);
			dos.writeUTF(field.getName());
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void afterSerializeField(ArrayList<TransportField> fields, Object serializedData) throws TransportException {
		try {
			DataOutputStream dos = (DataOutputStream) serializedData;
			dos.writeBoolean(BYTECODE_HAS_MORE_FIELDS_FALSE);
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected Object parseData(byte[] dataString) throws TransportException {
		try {
			ByteArrayInputStream bais = new ByteArrayInputStream(dataString);
			return new DataInputStream(bais);
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected Class<?> readClass(Object serializedData) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) serializedData;
			return classNames.get(dis.readUTF());
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected Object getTransportable(Object serializedData) {
		return serializedData;
	}

	@Override
	protected boolean isTransportableArray(Object serializedData) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) serializedData;
			return dis.readBoolean();
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected Object readTransportableArray(Object serializedData) throws TransportException {
		Object[] transpotableArray = null;
		try {
			DataInputStream dis = (DataInputStream) serializedData;
			int arrayLength = dis.readInt();
			if (arrayLength > 0) {
				transpotableArray = new Object[arrayLength];

				for (int arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
					transpotableArray[arrayIdx] = readTransportable(dis);
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
		return transpotableArray;
	}

	@Override
	protected Object readTransportable(Object serializedData) throws TransportException {
		Object transpotableObject = null;
		try {
			DataInputStream dis = (DataInputStream) serializedData;
			Class<?> clazz = readClass(serializedData);
			if (clazz.isArray()) {
				clazz = clazz.getComponentType();
			}

			transpotableObject = clazz.newInstance();

			if (dis != null) {
				ArrayList<TransportField> fields = classFields.get(clazz);
				HashMap<String, TransportField> classFieldsMap = new HashMap<String, TransportField>();

				if (fields != null) {
					for (int fieldIdx = 0; fieldIdx < fields.size(); fieldIdx++) {
						TransportField field = fields.get(fieldIdx);
						classFieldsMap.put(field.getName(), field);
					}
				}

				while (dis.readBoolean()) {
					TransportField field = classFieldsMap.get(dis.readUTF());
					deserializeField(field, dis, transpotableObject);
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
		return transpotableObject;
	}

	@Override
	protected void deserializedTransportable(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;

			if (field.isArray()) {
				int arrayLength = dis.readInt();
				Transportable[] transportableArray = new Transportable[arrayLength];
				for (int i = 0; i < arrayLength; i++) {
					transportableArray[i] = (Transportable) readTransportable(dis);
				}
				field.setValue(deserializedObject, transportableArray);
			} else {
				field.setValue(deserializedObject, (Transportable) readTransportable(dis));
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeBoolean(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;

			if (field.isArray()) {
				int arrayLength = dis.readInt();

				Boolean[] fieldValue = null;

				if (arrayLength > 0) {
					fieldValue = new Boolean[arrayLength];

					for (int dataIdx = 0; dataIdx < arrayLength; dataIdx++) {
						fieldValue[dataIdx] = dis.readBoolean();
					}
				}

				if (((Class<?>) field.getComponentValueType()).isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converBooleanArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, dis.readBoolean());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeByte(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;

			if (field.isArray()) {
				int arrayLength = dis.readInt();

				Byte[] fieldValue = null;

				if (arrayLength > 0) {
					fieldValue = new Byte[arrayLength];

					for (int dataIdx = 0; dataIdx < arrayLength; dataIdx++) {
						fieldValue[dataIdx] = dis.readByte();
					}
				}

				if (((Class<?>) field.getComponentValueType()).isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converByteArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, dis.readByte());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeCharacter(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;

			if (field.isArray()) {
				int arrayLength = dis.readInt();

				Character[] fieldValue = null;

				if (arrayLength > 0) {
					fieldValue = new Character[arrayLength];

					for (int dataIdx = 0; dataIdx < arrayLength; dataIdx++) {
						fieldValue[dataIdx] = dis.readChar();
					}
				}

				if (((Class<?>) field.getComponentValueType()).isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converCharacterArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, dis.readChar());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeShort(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;

			if (field.isArray()) {
				int arrayLength = dis.readInt();

				Short[] fieldValue = null;

				if (arrayLength > 0) {
					fieldValue = new Short[arrayLength];

					for (int dataIdx = 0; dataIdx < arrayLength; dataIdx++) {
						fieldValue[dataIdx] = dis.readShort();
					}
				}

				if (((Class<?>) field.getComponentValueType()).isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converShortArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, dis.readShort());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeInteger(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;

			if (field.isArray()) {
				int arrayLength = dis.readInt();

				Integer[] fieldValue = null;

				if (arrayLength > 0) {
					fieldValue = new Integer[arrayLength];

					for (int dataIdx = 0; dataIdx < arrayLength; dataIdx++) {
						fieldValue[dataIdx] = dis.readInt();
					}
				}

				if (((Class<?>) field.getComponentValueType()).isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converIntegerArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, dis.readInt());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeLong(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;

			if (field.isArray()) {
				int arrayLength = dis.readInt();

				Long[] fieldValue = null;

				if (arrayLength > 0) {
					fieldValue = new Long[arrayLength];

					for (int dataIdx = 0; dataIdx < arrayLength; dataIdx++) {
						fieldValue[dataIdx] = dis.readLong();
					}
				}

				if (((Class<?>) field.getComponentValueType()).isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converLongArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, dis.readLong());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeFloat(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;

			if (field.isArray()) {
				int arrayLength = dis.readInt();

				Float[] fieldValue = null;

				if (arrayLength > 0) {
					fieldValue = new Float[arrayLength];

					for (int dataIdx = 0; dataIdx < arrayLength; dataIdx++) {
						fieldValue[dataIdx] = dis.readFloat();
					}
				}

				if (((Class<?>) field.getComponentValueType()).isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converFloatArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, dis.readFloat());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeDouble(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;

			if (field.isArray()) {
				int arrayLength = dis.readInt();

				Double[] fieldValue = null;

				if (arrayLength > 0) {
					fieldValue = new Double[arrayLength];

					for (int dataIdx = 0; dataIdx < arrayLength; dataIdx++) {
						fieldValue[dataIdx] = dis.readDouble();
					}
				}

				if (((Class<?>) field.getComponentValueType()).isPrimitive()) {
					field.setValue(deserializedObject, TransporterUtil.converDoubleArray(fieldValue));
				} else {
					field.setValue(deserializedObject, fieldValue);
				}
			} else {
				field.setValue(deserializedObject, dis.readDouble());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeString(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;

			if (field.isArray()) {
				int arrayLength = dis.readInt();

				String[] fieldValue = null;

				if (arrayLength > 0) {
					fieldValue = new String[arrayLength];

					for (int dataIdx = 0; dataIdx < arrayLength; dataIdx++) {
						fieldValue[dataIdx] = dis.readUTF();
					}
				}

				field.setValue(deserializedObject, fieldValue);
			} else {
				field.setValue(deserializedObject, dis.readUTF());
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected void deserializeDate(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;

			if (field.isArray()) {
				int arrayLength = dis.readInt();

				Date[] fieldValue = null;

				if (arrayLength > 0) {
					fieldValue = new Date[arrayLength];

					for (int dataIdx = 0; dataIdx < arrayLength; dataIdx++) {
						fieldValue[dataIdx] = simpleDateFormat.parse(dis.readUTF());
					}
				}

				field.setValue(deserializedObject, fieldValue);
			} else {
				field.setValue(deserializedObject, simpleDateFormat.parse(dis.readUTF()));
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	protected void deserializeArrayList(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;
			Class<?> genericValueClass = (Class<?>) field.getComponentValueType();

			if (field.isArray()) {
				int arrayLength = dis.readInt();
				ArrayList[] deserializedDataArray = new ArrayList[arrayLength];
				for (int dataIdx = 0; dataIdx < arrayLength; dataIdx++) {
					ArrayList<Object> deserializedDataObject = (ArrayList<Object>) ((Class<?>) field.getRawType()).newInstance();
					readArrayList(field, dis, genericValueClass, deserializedDataObject);
					deserializedDataArray[dataIdx] = deserializedDataObject;
				}
				field.setValue(deserializedObject, deserializedDataArray);
			} else {
				ArrayList<Object> deserializedDataObject = (ArrayList<Object>) ((Class<?>) field.getRawType()).newInstance();
				readArrayList(field, dis, genericValueClass, deserializedDataObject);
				field.setValue(deserializedObject, deserializedDataObject);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void readArrayList(TransportField field, Object valueArray, Class<?> genericValueClass, Object deserializedDataObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) valueArray;
			int arrayLength = dis.readInt();

			if ((Boolean.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < arrayLength; arrarIdx++) {
					((ArrayList<Boolean>) deserializedDataObject).add(dis.readBoolean());
				}
			} else if ((Byte.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < arrayLength; arrarIdx++) {
					((ArrayList<Byte>) deserializedDataObject).add(dis.readByte());
				}
			} else if ((Character.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < arrayLength; arrarIdx++) {
					((ArrayList<Character>) deserializedDataObject).add(dis.readChar());
				}
			} else if ((Short.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < arrayLength; arrarIdx++) {
					((ArrayList<Short>) deserializedDataObject).add(dis.readShort());
				}
			} else if ((Integer.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < arrayLength; arrarIdx++) {
					((ArrayList<Integer>) deserializedDataObject).add(dis.readInt());
				}
			} else if ((Long.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < arrayLength; arrarIdx++) {
					((ArrayList<Long>) deserializedDataObject).add(dis.readLong());
				}
			} else if ((Float.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < arrayLength; arrarIdx++) {
					((ArrayList<Float>) deserializedDataObject).add(dis.readFloat());
				}
			} else if ((Double.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < arrayLength; arrarIdx++) {
					((ArrayList<Double>) deserializedDataObject).add(dis.readDouble());
				}
			} else if ((String.class).equals(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < arrayLength; arrarIdx++) {
					((ArrayList<String>) deserializedDataObject).add(dis.readUTF());
				}
			} else if (isTransportable(genericValueClass)) {
				for (int arrarIdx = 0; arrarIdx < arrayLength; arrarIdx++) {
					((ArrayList<Transportable>) deserializedDataObject).add((Transportable) readTransportable(dis));
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	protected void deserializeHashMap(TransportField field, Object objectData, Object deserializedObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) objectData;
			Class<?> genericValueClass = (Class<?>) field.getComponentValueType();

			if (field.isArray()) {
				int arrayLength = dis.readInt();
				HashMap[] deserializedDataArray = new HashMap[arrayLength];
				for (int dataIdx = 0; dataIdx < arrayLength; dataIdx++) {
					HashMap<String, Object> deserializedDataObject = (HashMap<String, Object>) ((Class<?>) field.getRawType()).newInstance();
					readHashMap(field, dis, genericValueClass, deserializedDataObject);
					deserializedDataArray[dataIdx] = deserializedDataObject;
				}
				field.setValue(deserializedObject, deserializedDataArray);
			} else {
				HashMap<String, Object> deserializedDataObject = (HashMap<String, Object>) ((Class<?>) field.getRawType()).newInstance();
				readHashMap(field, dis, genericValueClass, deserializedDataObject);
				field.setValue(deserializedObject, deserializedDataObject);
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void readHashMap(TransportField field, Object valueObject, Class<?> genericValueClass, Object deserializedDataObject) throws TransportException {
		try {
			DataInputStream dis = (DataInputStream) valueObject;
			int arrayLength = dis.readInt();

			if ((Boolean.class).equals(genericValueClass)) {
				for (int arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
					String key = dis.readUTF();
					((HashMap<String, Boolean>) deserializedDataObject).put(key, dis.readBoolean());
				}
			} else if ((Byte.class).equals(genericValueClass)) {
				for (int arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
					String key = dis.readUTF();
					((HashMap<String, Byte>) deserializedDataObject).put(key, dis.readByte());
				}
			} else if ((Character.class).equals(genericValueClass)) {
				for (int arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
					String key = dis.readUTF();
					((HashMap<String, Character>) deserializedDataObject).put(key, dis.readChar());
				}
			} else if ((Short.class).equals(genericValueClass)) {
				for (int arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
					String key = dis.readUTF();
					((HashMap<String, Short>) deserializedDataObject).put(key, dis.readShort());
				}
			} else if ((Integer.class).equals(genericValueClass)) {
				for (int arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
					String key = dis.readUTF();
					((HashMap<String, Integer>) deserializedDataObject).put(key, dis.readInt());
				}
			} else if ((Long.class).equals(genericValueClass)) {
				for (int arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
					String key = dis.readUTF();
					((HashMap<String, Long>) deserializedDataObject).put(key, dis.readLong());
				}
			} else if ((Float.class).equals(genericValueClass)) {
				for (int arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
					String key = dis.readUTF();
					((HashMap<String, Float>) deserializedDataObject).put(key, dis.readFloat());
				}
			} else if ((Double.class).equals(genericValueClass)) {
				for (int arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
					String key = dis.readUTF();
					((HashMap<String, Double>) deserializedDataObject).put(key, dis.readDouble());
				}
			} else if ((String.class).equals(genericValueClass)) {
				for (int arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
					String key = dis.readUTF();
					((HashMap<String, String>) deserializedDataObject).put(key, dis.readUTF());
				}
			} else if (isTransportable(genericValueClass)) {
				for (int arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
					String key = dis.readUTF();
					((HashMap<String, Transportable>) deserializedDataObject).put(key, (Transportable) readTransportable(dis));
				}
			}
		} catch (Exception e) {
			throw new TransportException(e);
		}
	}

	@Override
	protected byte[] stringify(Object serilizedData) throws TransportException {
		byte[] toRet = null;
		try {
			toRet = baos.toByteArray();
		} catch (Exception e) {
			throw new TransportException(e);
		}

		return toRet;

	}

	/*
	 * @Override public byte[] tranportMap(Map<String, Transportable>
	 * mergedModel) throws TransportException { ByteArrayOutputStream baos =
	 * null; try { baos = new ByteArrayOutputStream(); DataOutputStream dos =
	 * new DataOutputStream(baos); dos.write(mergedModel.size());
	 * 
	 * Iterator<String> keyIterator = (mergedModel.keySet()).iterator(); while
	 * (keyIterator.hasNext()) { String key = keyIterator.next();
	 * dos.writeUTF(key); dos.write(serialize(mergedModel.get(key))); } } catch
	 * (Exception e) { if (e instanceof TransportException) { throw
	 * (TransportException)e; } else { throw new TransportException(e); } }
	 * return baos.toByteArray(); }
	 */

}
